Delay Prediction of Planes at New York.

Content

  1. Problem Statement and Understanding.
  2. Reading and binding the test data.
  3. Data Cleaning.
  4. Feature Engineering.
  5. Checking and handling unbalanced data.
  6. Checking for multicollinearity.
  7. Model Building 7.1) classification 7.1.1) Logistic Regression. 7.1.2) KNN 7.1.3) Decision Tree. 7.1.4) Random Forest. 7.1.5) SVM. 7.1.6) XGboost.
  8. Model selection for deployment. 9)conclusion.

Problem Statement

Understand the key factors through visualization that cause the delay Predict the possibility of delay in the future.

Understanding

The given datasets had the flight delay details of 2 Airports in the US namely JFK(NewYork) and DFW(Dallas).Identify the features which cause delays & use ML to predict future delays.

libraries used.

#used for reading and subsetting the data
library(data.table)
library(purrr)
#used for converting the format of the date column 
library(lubridate)
#used for plotting graphs
library(ggplot2)
library(plotly)
#used for smote function to do under sampling and over sampling
library(DMwR)
#The library for cross validation
library(caret)
library(mlbench)
#decision tree model building packages 
library(rpart)
#decision tree plotting packages 
library(RColorBrewer)
library(rattle)
#The package for random forest function
library(MASS)
library(randomForest)
#packages for xgboost
library(xgboost)
library(Matrix)
library(readr)
library(car)
#For one hot encode function
library(mltools)
#library for ROC curve
library(ROCR)
library(car)
#library for summarise function 
library(dplyr)
#This Library is used for reading Excel file.
library(readxl)
#For calculating the Geo distance.
library(geosphere)

Reading the csv files of all the airlines who ’s origin airport is NewYork.

#data<-fread("Detailed_Statistics_Departures.csv",skip = 7,stringsAsFactors = TRUE)
Total_data<- 
   list.files(pattern = "*.csv") %>% 
    map_df(~fread(.,skip = 7,stringsAsFactors = TRUE))
Discarded single-line footer: <<SOURCE: Bureau of Transportation Statistics>>Discarded single-line footer: <<SOURCE: Bureau of Transportation Statistics>>Discarded single-line footer: <<SOURCE: Bureau of Transportation Statistics>>Discarded single-line footer: <<SOURCE: Bureau of Transportation Statistics>>Discarded single-line footer: <<SOURCE: Bureau of Transportation Statistics>>Discarded single-line footer: <<SOURCE: Bureau of Transportation Statistics>>Discarded single-line footer: <<SOURCE: Bureau of Transportation Statistics>>Discarded single-line footer: <<SOURCE: Bureau of Transportation Statistics>>Discarded single-line footer: <<SOURCE: Bureau of Transportation Statistics>>Discarded single-line footer: <<SOURCE: Bureau of Transportation Statistics>>Discarded single-line footer: <<SOURCE: Bureau of Transportation Statistics>>Unequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorUnequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorUnequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorUnequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorUnequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorUnequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorUnequal factor levels: coercing to characterbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vectorbinding character and factor vector, coercing into character vector

Data Cleaning

Now checking for the NA values for both train and test data sets.

#Checking the NA 'S at entire data set of train and test
cat("The Number of NA 'S in the data: ", sum(Total_data=="na"))
The Number of NA 'S in the data:  0
#checking for the empty sells in the table
cat("\nThe Number of blank cell 'S in the data: ", sum(Total_data==""))

The Number of blank cell 'S in the data:  200

As we see above output their are 200 empty spaces in the training data, so now we are going to see the empty rows for finding the reason that why they are empty

Now seing in which columns empty spaces are present.

apply(Total_data,2,function(x)sum(x==""))
                            Carrier Code                        Date (MM/DD/YYYY)                            Flight Number 
                                       0                                        0                                        0 
                             Tail Number                      Destination Airport                 Scheduled departure time 
                                     200                                        0                                        0 
                   Actual departure time         Scheduled elapsed time (Minutes)            Actual elapsed time (Minutes) 
                                       0                                        0                                        0 
               Departure delay (Minutes)                          Wheels-off time                  Taxi-Out time (Minutes) 
                                       0                                        0                                        0 
                 Delay Carrier (Minutes)                  Delay Weather (Minutes) Delay National Aviation System (Minutes) 
                                       0                                        0                                        0 
                Delay Security (Minutes)    Delay Late Aircraft Arrival (Minutes) 
                                       0                                        0 

As we see above that Tail Number has 200 empty cells.

Now I am going to see the rows of that particular column to find the reason of empty cells

#This command is use to see all the empty rows.
Total_data[`Tail Number`==""]

As we see in all these rows scheduled departure time was given but Actual departure time 00:00 ,Actual elapsed time is also 0 and all sort of delay columns are also 0 ,so by this we can conclude that the flights has got cancled for some reason or the data has not been captured for this particular flights.So this kind of data is not much used in the prediction so for now we are removing all the rows which are empty.

Removing all the rows which are empty.

setkey(Total_data,`Tail Number`)
Total_data<-Total_data[!""]

Now again checking wheather all the empty cell has got removed or not in train data

#Checking the NA 'S at entire data set of train and test
cat("The Number of blank cells  at Training data set: ", sum(Total_data==""))
The Number of blank cells  at Training data set:  0

so Now we our training data set free of empty cells.

Generally we should find and treate the outliers but due to less time issues and some Machine Learning Algorithm which i am using to build model are robust to outlier so for now i am not considering it.

Feature Engineering

Reading the Coordinates of the Destination Airports from the file.

lat_long<-as.data.table(read_excel("Lat_Long.xlsx"))
#converting string column as factor.
lat_long$Destination<-as.factor(lat_long$Destination)

Adding longitude and latitude columns for Origin Airport.

#Adding the columns
Total_data$`Start Station Longitude`<- -73.8630
Total_data$`Start Station Latitude`<- 40.7636

Adding Longitude and Latitude of Destination Airports.

Total_data<- merge(Total_data,lat_long,by.x ="Destination Airport",by.y = "Destination")

Adding the column of Geo_distance between source airport to destination airport.

Total_data[,distance := round(distHaversine(matrix(c(`Start Station Longitude`,`Start Station Latitude`), ncol = 2),matrix(c(Long,Lat),ncol = 2),r=6378137),2)]

we are removing these columns because these columns does not effect our prediction. 1) Flight Number 2) Destination Airport 3) Carrier Code 4) Tail Number 5) Start Station Longitude 6) Start Station Latitude 7) Lat 8) Long

Total_data[ ,`:=`(`Flight Number` = NULL, `Destination Airport` = NULL,`Carrier Code`= NULL,`Tail Number`= NULL,`Start Station Longitude`=NULL,`Start Station Latitude`=NULL,Lat=NULL,Long=NULL)]

so now we are converting the date columns to the date formate.

#Now converting the date column.
#we found 2 date format in data
mdy <- mdy(Total_data$`Date (MM/DD/YYYY)`)
dmy <- dmy(Total_data$`Date (MM/DD/YYYY)`)
 207846 failed to parse.
mdy[is.na(mdy)] <- dmy[is.na(mdy)] # some dates are ambiguous, here we give
Total_data$`Date (MM/DD/YYYY)`<- mdy # mdy precedence over dmy

Now we are dividing the following columns by hours and minutes 1)1)Scheduled departure time 2)Actual departure time

#Now we are dividing Scheduled departure time column to scheduled_departure_time_hours and scheduled_departure_time_minutes
Total_data$`Scheduled departure time hours`<-hour(strptime(Total_data$`Scheduled departure time`, format = '%H:%M', 'GMT'))
Total_data$`Scheduled departure time minutes`<-minute(strptime(Total_data$`Scheduled departure time`,format = '%H:%M', 'GMT'))
#Now we are dividing Actual departure time departure time column to Actual_departure_time_hours and Actual_departure_time_minutes
Total_data$`Actual departure time hours`<-hour(strptime(Total_data$`Actual departure time`, format = '%H:%M', 'GMT'))
Total_data$`Actual departure time minutes`<-minute(strptime(Total_data$`Actual departure time`,format = '%H:%M', 'GMT'))
#Now removing the original Scheduled departure time column
Total_data$`Scheduled departure time`<-NULL
#Now removing the actual departure time column
Total_data$`Actual departure time`<-NULL
#Now removing the wheels of time as its not useful at model building.
Total_data$`Wheels-off time`<-NULL

Now extracting months and weekdays from the Date column in train data set.Removing Date column

#this command is use to extract months
Total_data$months<-as.factor(month(Total_data$`Date (MM/DD/YYYY)`))
#this command is used to extract weekdays
Total_data$weekDays<-as.factor(weekdays(Total_data$`Date (MM/DD/YYYY)`))
#Removing Date column
#train$`Date (MM/DD/YYYY)`<-NULL

Now extracting seasons from Date in the training data set.we are extracting seasons according to USA. 1) Summer - June,July,August (6,7,8) 2) Autumn - Sept,Oct,Nov (9,10,11) 3) Winter - December,Jan,Feb (12,1,2) 4) Spring - March,Aprial,May (3,4,5) Now creating the new column of seasons.

indx <- setNames( rep(c('winter', 'spring', 'summer',
                   'fall'),each=3), c(c(12,1,2),c(3,4,5),c(6,7,8),c(9,10,11)))
Total_data[,seasons := as.factor(unname(indx[as.character(month(Total_data$`Date (MM/DD/YYYY)`))]))]

Now extracting years from the date.

Total_data$years<-as.factor(year(Total_data$`Date (MM/DD/YYYY)`))

2016

Now we are subsetting data of 2016.

train_2016<-Total_data[years=="2016"]
#extracting day 
train_2016$day<-as.factor(day(train_2016$`Date (MM/DD/YYYY)`))

Holidays list of USA at Year 2016.

Holidays

Day Dates

Fri Jan 1 Mon Jan 18 Mon Feb 15 Fri Apr 15 Sun May 8 Mon May 30 Sun June 19 Mon July 4 Mon Sept 5 Mon Oct 10 Fri Nov 11 Thur Nov 24 Fri Nov 25 Mon Dec 26

Now we are creating the column Holiday for the train_2016 data.

#Inserting the holiday column. 
train_2016$Holiday<-as.factor(ifelse((train_2016$months == "1" & train_2016$weekDays=="Friday" & train_2016$day=="1") | (train_2016$months == "1" & train_2016$weekDays=="Monday" & train_2016$day=="18") | (train_2016$months == "2" & train_2016$weekDays=="Monday" & train_2016$day=="15") | (train_2016$months == "4" & train_2016$weekDays=="Friday" & train_2016$day=="15") |(train_2016$months == "5" & train_2016$weekDays=="Sunday" & train_2016$day=="8") |(train_2016$months == "5" & train_2016$weekDays=="Monday" & train_2016$day=="30") |(train_2016$months == "6" & train_2016$weekDays=="Sunday" & train_2016$day=="19") |(train_2016$months == "7" & train_2016$weekDays=="Monday" & train_2016$day=="4") |(train_2016$months == "9" & train_2016$weekDays=="Monday" & train_2016$day=="5") |(train_2016$months == "10" & train_2016$weekDays=="Monday" & train_2016$day=="10") |(train_2016$months == "11" & train_2016$weekDays=="Friday" & train_2016$day=="11") |(train_2016$months == "11" & train_2016$weekDays=="Thursday" & train_2016$day=="24") |(train_2016$months == "11" & train_2016$weekDays=="Friday" & train_2016$day=="25") |(train_2016$months == "12" & train_2016$weekDays=="Monday" & train_2016$day=="26")== TRUE,1,0))

1 - means yes there was holiday.

0 - means No there was no holiday.

Holidays list of USA at Year 2017.

2017

Now subsetting the 2017 data from train.

train_2017<-Total_data[years=="2017"]
#extracting day 
train_2017$day<-as.factor(day(train_2017$`Date (MM/DD/YYYY)`))

Holidays list of USA at Year 2017.

Holidays

Day Dates

Monday Jan 2 Monday Jan 16 Monday Feb 20 Monday April 17 Sunday May 14 Monday May 29 Sunday June 18 Tuesday July 4 Monday September 04 Monday october 09 Friday November 10 Saturday November 11 Monday November 13 Thursday November 23 Friday November 24 Monday December 25

Now we are creating the column Holiday for the train_2016 data.

#Inserting the holiday column. 
train_2017$Holiday <- as.factor(ifelse((train_2017$months == "1" & train_2017$weekDays=="Monday" & train_2017$day=="2") | (train_2017$months == "1" & train_2017$weekDays=="Monday" & train_2017$day=="16") | (train_2017$months == "2" & train_2017$weekDays=="Monday" & train_2017$day=="20") | (train_2017$months == "4" & train_2017$weekDays=="Monday" & train_2017$day=="17") |(train_2017$months == "5" & train_2017$weekDays=="Sunday" & train_2017$day=="14") |(train_2017$months == "5" & train_2017$weekDays=="Monday" & train_2017$day=="29") |(train_2017$months == "6" & train_2017$weekDays=="Sunday" & train_2017$day=="18") |(train_2017$months == "7" & train_2017$weekDays=="Tuesday" & train_2017$day=="4") |(train_2017$months == "9" & train_2017$weekDays=="Monday" & train_2017$day=="4") |(train_2017$months == "10" & train_2017$weekDays=="Monday" & train_2017$day=="9") |(train_2017$months == "11" & train_2017$weekDays=="Friday" & train_2017$day=="10") |(train_2017$months == "11" & train_2017$weekDays=="Saturday" & train_2017$day=="11") |(train_2017$months == "11" & train_2017$weekDays=="Monday" & train_2017$day=="13") |(train_2017$months == "11" & train_2017$weekDays=="Thursday" & train_2017$day=="23")|(train_2017$months == "11" & train_2017$weekDays=="Friday" & train_2017$day=="24")|(train_2017$months == "12" & train_2017$weekDays=="Monday" & train_2017$day=="25") == TRUE,1,0))

Now joining the Two years data set.

Total_data1<-rbind(setDT(train_2016), setDT(train_2017), fill=TRUE)
#removing unwanted data set
rm(train_2016)
rm(train_2017)

2018

test<-Total_data[years=="2018"]
test$day<-day(test$`Date (MM/DD/YYYY)`)

Holidays list of USA at Year 2018.

Holidays

Day Dates

Monday Jan 1 Monday Jan 15 Monday Feb 19 Saturday March 31 Monday May 28 Wednesday July 4 Monday Sept 3 Monday Nov 12 Thursday Nov 22 Friday Nov 23 Tuesday December 25

Now we are creating the column Holiday for the train_2016 data.

#Inserting the holiday column. 
test$Holiday<-as.factor(ifelse((test$months == "1" & test$weekDays=="Monday" & test$day=="1") | (test$months == "1" & test$weekDays=="Monday" & test$day=="15") | (test$months == "2" & test$weekDays=="Monday" & test$day=="19") | (test$months == "3" & test$weekDays=="Saturday" & test$day=="31") |(test$months == "5" & test$weekDays=="Monday" & test$day=="28") |(test$months == "7" & test$weekDays=="Wednesday" & test$day=="4") |(test$months == "9" & test$weekDays=="Monday" & test$day=="3") |(test$months == "11" & test$weekDays=="Monday" & test$day=="12") |(test$months == "11" & test$weekDays=="Thursday" & test$day=="22") |(test$months == "11" & test$weekDays=="Friday" & test$day=="23") |(test$months == "12" & test$weekDays=="Tuesday" & test$day=="25")== TRUE,1,0))

Joining the tables.

Total_data1<-rbind(setDT(Total_data1), setDT(test), fill=TRUE)

2019

test<-Total_data[years=="2019"]
test$day<-day(test$`Date (MM/DD/YYYY)`)

Holidays list of USA at Year 2019.

Holidays

Reason Day Date

New Year’s Day Monday January 1

Birthday of Martin Luther King Jr.: Monday January 21

Birthday of George Washington (President’s Day): Monday February 18

Memorial Day: Monday May 27

Independence Day: Thursday July 4

Labor Day: Monday September 2

Columbus Day: Monday October 14

Veterans Day: Monday November 11

Thanksgiving Day: Thursday November 28

Christmas Day: Wednesday December 25

Other important holidays to note that you don’t get off for:

Groundhog Day: Saturday February 2

Valentine’s Day: Thursday February 14

Saint Patrick’s Day: Sunday March 17

Tax Day: Monday April 15

Good Friday: Friday April 19

Easter: Sunday April 21

Cinco de Mayo: Sunday May 5

Mother’s Day: Sunday May 12

Father’s Day: Sunday June 16

Halloween: Thursday October 31

Black Friday: Friday November 29

#Inserting the holiday column. 
test$Holiday<-as.factor(ifelse((test$months == "1" & test$weekDays=="Monday" & test$day=="1") | (test$months == "1" & test$weekDays=="Monday" & test$day=="21") | (test$months == "2" & test$weekDays=="Monday" & test$day=="18") | (test$months == "5" & test$weekDays=="Monday" & test$day=="27") |(test$months == "7" & test$weekDays=="Thursday" & test$day=="4") |(test$months == "9" & test$weekDays=="Monday" & test$day=="2") |(test$months == "10" & test$weekDays=="Monday" & test$day=="14") |(test$months == "11" & test$weekDays=="Monday" & test$day=="11") |(test$months == "11" & test$weekDays=="Thursday" & test$day=="28") |(test$months == "12" & test$weekDays=="Wednesday" & test$day=="25") |(test$months == "2" & test$weekDays=="Saturday" & test$day=="2")|(test$months == "2" & test$weekDays=="Thursday" & test$day=="14")|(test$months == "3" & test$weekDays=="Sunday" & test$day=="17")|(test$months == "4" & test$weekDays=="Monday" & test$day=="15")|(test$months == "4" & test$weekDays=="Friday" & test$day=="19")|(test$months == "4" & test$weekDays=="Sunday" & test$day=="21")|(test$months == "5" & test$weekDays=="Sunday" & test$day=="5")|(test$months == "5" & test$weekDays=="Sunday" & test$day=="12")|(test$months == "6" & test$weekDays=="Sunday" & test$day=="16")|(test$months == "10" & test$weekDays=="Thursday" & test$day=="31")|(test$months == "11" & test$weekDays=="Friday" & test$day=="29")== TRUE,1,0))

Joining the tables.

Total_data<-rbind(setDT(Total_data1), setDT(test), fill=TRUE)
rm(Total_data1)

Now extracting Morning,Noon,Evening and Night,the following the timing classifications. 5 Hours - 11 Hours :- Morning 12 Hours - 16 Hours :- Noon 17 Hours - 19 Hours :- Evening 20 Hours - 4 Hours :- Night.

Now inserting th DayCycle column into train data set.

Total_data[,DayCycle:=as.factor( ifelse(
  `Scheduled departure time hours` >= 5 & `Scheduled departure time hours`<=11 , 'Morning',
    ifelse(`Scheduled departure time hours` >= 12 & `Scheduled departure time hours`<=16,'Noon' ,
      ifelse(`Scheduled departure time hours` >= 17 & `Scheduled departure time hours`<=19, 'Evening', 
          "Night"   )
    )
  )
)
]

creating the target variable by the formula ((actual_elapsed time - scheduled_elapsed time)+departure time)<=0 no_delay >=1 is delay

#creating the target variable which is categorical variable.
Total_data$Delay<-as.factor(ifelse((Total_data$`Actual elapsed time (Minutes)`- Total_data$`Scheduled elapsed time (Minutes)`)+Total_data$`Departure delay (Minutes)` <= 0,0,1))
  1. 1 - Delayed
  2. 0 - Not Delayed

Now removing unwanted features from the train data set.

Total_2018<-Total_data
Total_2018$years<-NULL
Total_2018$day<-NULL
Total_2018$`Date (MM/DD/YYYY)`<-NULL
rm(test)

Removing the actual elaps time ,Scheduled elapsed time (Minutes),Departure delay (Minutes) from trainig and testing data as these three columns are highly correlated to target varible.

#Removing from traing data
Total_2018$`Actual elapsed time (Minutes)`<-NULL
Total_2018$`Departure delay (Minutes)`<-NULL
Total_2018$`Scheduled elapsed time (Minutes)`<-NULL
#Parameter for the function.
#parameter 1 :- Number of correct predictions for class 0
#parameter 2 :- Number of wrong predictions for class 0
#parameter 3 :- Number of correct predictions for class 1
#parameter 4 :- Number of wrong predictions for class 1
graphConfusionMatrix<-function(correct_class_a,wrong_class_a,correct_class_b,wrong_class_b){
  
  #Creating the data for the plot.
  x <- data.frame("About_results" = c("Correct_Prediction","Wrong_Prediction"), "Values" = c(correct_class_a,wrong_class_a))
  y <- data.frame("About_results" = c("Correct_Prediction","Wrong_Prediction"), "Values" = c(correct_class_b,wrong_class_b))
  
  #ploting the graph.
  p <- plot_ly() %>%
   add_pie(data = count(x,About_results), labels = ~About_results, values =x$Values ,
         name = "class 0", domain = list(row = 0, column = 0)) %>%
 add_pie(data = count(y,About_results), labels = ~About_results, values = y$Values,
         name = "class 1", domain = list(row = 0, column = 1)) %>%
   layout(title = "Visualization Of Confusion Matrix",showlegend = T,
        grid=list(rows=1, columns=2),
        xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
        yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE))
  #Displaying the graphs
  p
  #removing unwanted dataframes.
  #rm(x)
  #rm(y)
}
names(Total_2018) <- make.names(names(Total_2018))

Encoding the data for XGBoost Model.

#Encoding the  data set
Total_data_encoded<-one_hot(Total_2018)

While doing onehot encoding we have got two columns for the target variable.so we should remove one of the column

Total_data_encoded$Delay_0<-NULL
dtestfinal<-xgb.DMatrix(as.matrix(Total_data_encoded[,-"Delay_1"]), label = as.matrix(Total_data_encoded$Delay_1))

Now importing out model.

model<- xgb.load('xgb_all_data.model')

Now we are going to fit the new data to our Model.

xgbpred <- predict (model,dtestfinal,type = "class")

As our model threshold is 0.5, now we are classifing the predictions.

xgbpred <- ifelse (xgbpred >= 0.5,1,0)

Now we are going to check on confusion matrix

confusionMatrix(as.factor(Total_data_encoded$Delay_1),as.factor(xgbpred),positive = "1")
Confusion Matrix and Statistics

          Reference
Prediction      0      1
         0 200490  21952
         1  27903  91499
                                         
               Accuracy : 0.8542         
                 95% CI : (0.853, 0.8553)
    No Information Rate : 0.6681         
    P-Value [Acc > NIR] : < 2.2e-16      
                                         
                  Kappa : 0.6754         
                                         
 Mcnemar's Test P-Value : < 2.2e-16      
                                         
            Sensitivity : 0.8065         
            Specificity : 0.8778         
         Pos Pred Value : 0.7663         
         Neg Pred Value : 0.9013         
             Prevalence : 0.3319         
         Detection Rate : 0.2677         
   Detection Prevalence : 0.3493         
      Balanced Accuracy : 0.8422         
                                         
       'Positive' Class : 1              
                                         
graphConfusionMatrix(200490 ,21952, 91499,27903)

Lets see which is the best threshold value for our model.

Now Drawing the ROC cURVE for finding out the ideal threshold value at which true positive and false positive get balanced.

ROCpred<-prediction(xgbpred,Total_data_encoded$Delay_1)
ROCperf<-performance(ROCpred,"tpr","fpr")
plot(ROCperf,col="blue",print.cutoffs.at=seq(0.1,by=0.1,text.adj=c(-0.2,1.7),cex=0.7))
In seq.default(0.1, by = 0.1, text.adj = c(-0.2, 1.7), cex = 0.7) :
 extra arguments 㤼㸱text.adj㤼㸲, 㤼㸱cex㤼㸲 will be disregarded

yes its predicting good for the test data.

Building the model on this data.

#default parameters
#params <- list(booster = "gbtree", objective = "binary:logistic", eta=0.2, max_depth=4, min_child_weight=2, subsample=1, colsample_bytree=1)

#find best nround
#cv<-xgb.cv( params = params, data = dtestfinal, nrounds = 1000, nfold = 5,gamma=0, showsd = T, stratified = T, print.every.n = 10, early.stop.round = 20, maximize = F)
#cv$best_iteration
#print(cv)
#print(cv, verbose=TRUE)
#first default - model training
#xgb1 <- xgb.train (params = params, data = dtestfinal, nrounds = 973, watchlist = list(train=dtestfinal), print.every.n = 10, early.stop.round = 10, maximize = F , eval_metric = "error")
LS0tDQp0aXRsZTogIkZsaWdodHMgRGVsYXkgcHJlZGljdGlvbiBhdCBOZXcgWW9yay4iDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KI0RlbGF5IFByZWRpY3Rpb24gb2YgUGxhbmVzIGF0IE5ldyBZb3JrLg0KDQojQ29udGVudA0KICANCjEpIFByb2JsZW0gU3RhdGVtZW50IGFuZCBVbmRlcnN0YW5kaW5nLg0KMikgUmVhZGluZyBhbmQgYmluZGluZyB0aGUgdGVzdCBkYXRhLg0KMykgRGF0YSBDbGVhbmluZy4NCjQpIEZlYXR1cmUgRW5naW5lZXJpbmcuDQo1KSBDaGVja2luZyBhbmQgaGFuZGxpbmcgdW5iYWxhbmNlZCBkYXRhLg0KNikgQ2hlY2tpbmcgZm9yIG11bHRpY29sbGluZWFyaXR5Lg0KNykgTW9kZWwgQnVpbGRpbmcNCiAgICA3LjEpIGNsYXNzaWZpY2F0aW9uDQogICAgICA3LjEuMSkgTG9naXN0aWMgUmVncmVzc2lvbi4gDQogICAgICA3LjEuMikgS05ODQogICAgICA3LjEuMykgRGVjaXNpb24gVHJlZS4NCiAgICAgIDcuMS40KSBSYW5kb20gRm9yZXN0Lg0KICAgICAgNy4xLjUpIFNWTS4NCiAgICAgIDcuMS42KSBYR2Jvb3N0Lg0KOCkgTW9kZWwgc2VsZWN0aW9uIGZvciBkZXBsb3ltZW50Lg0KOSljb25jbHVzaW9uLg0KDQojUHJvYmxlbSBTdGF0ZW1lbnQNCg0KVW5kZXJzdGFuZCB0aGUga2V5IGZhY3RvcnMgdGhyb3VnaCB2aXN1YWxpemF0aW9uIHRoYXQgY2F1c2UgdGhlIGRlbGF5IFByZWRpY3QgdGhlIHBvc3NpYmlsaXR5IG9mIGRlbGF5IGluIHRoZSBmdXR1cmUuDQoNCiNVbmRlcnN0YW5kaW5nDQoNClRoZSBnaXZlbiBkYXRhc2V0cyBoYWQgdGhlIGZsaWdodCBkZWxheSBkZXRhaWxzIG9mIDIgQWlycG9ydHMgaW4gdGhlIFVTIG5hbWVseSBKRksoTmV3WW9yaykgYW5kIERGVyhEYWxsYXMpLklkZW50aWZ5IHRoZSBmZWF0dXJlcyB3aGljaCBjYXVzZSBkZWxheXMgJiB1c2UgTUwgdG8gcHJlZGljdCBmdXR1cmUgZGVsYXlzLg0KIA0KbGlicmFyaWVzIHVzZWQuDQpgYGB7cn0NCiN1c2VkIGZvciByZWFkaW5nIGFuZCBzdWJzZXR0aW5nIHRoZSBkYXRhDQpsaWJyYXJ5KGRhdGEudGFibGUpDQpsaWJyYXJ5KHB1cnJyKQ0KI3VzZWQgZm9yIGNvbnZlcnRpbmcgdGhlIGZvcm1hdCBvZiB0aGUgZGF0ZSBjb2x1bW4gDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCiN1c2VkIGZvciBwbG90dGluZyBncmFwaHMNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkocGxvdGx5KQ0KI3VzZWQgZm9yIHNtb3RlIGZ1bmN0aW9uIHRvIGRvIHVuZGVyIHNhbXBsaW5nIGFuZCBvdmVyIHNhbXBsaW5nDQpsaWJyYXJ5KERNd1IpDQojVGhlIGxpYnJhcnkgZm9yIGNyb3NzIHZhbGlkYXRpb24NCmxpYnJhcnkoY2FyZXQpDQpsaWJyYXJ5KG1sYmVuY2gpDQojZGVjaXNpb24gdHJlZSBtb2RlbCBidWlsZGluZyBwYWNrYWdlcyANCmxpYnJhcnkocnBhcnQpDQojZGVjaXNpb24gdHJlZSBwbG90dGluZyBwYWNrYWdlcyANCmxpYnJhcnkoUkNvbG9yQnJld2VyKQ0KbGlicmFyeShyYXR0bGUpDQojVGhlIHBhY2thZ2UgZm9yIHJhbmRvbSBmb3Jlc3QgZnVuY3Rpb24NCmxpYnJhcnkoTUFTUykNCmxpYnJhcnkocmFuZG9tRm9yZXN0KQ0KI3BhY2thZ2VzIGZvciB4Z2Jvb3N0DQpsaWJyYXJ5KHhnYm9vc3QpDQpsaWJyYXJ5KE1hdHJpeCkNCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KGNhcikNCiNGb3Igb25lIGhvdCBlbmNvZGUgZnVuY3Rpb24NCmxpYnJhcnkobWx0b29scykNCiNsaWJyYXJ5IGZvciBST0MgY3VydmUNCmxpYnJhcnkoUk9DUikNCmxpYnJhcnkoY2FyKQ0KI2xpYnJhcnkgZm9yIHN1bW1hcmlzZSBmdW5jdGlvbiANCmxpYnJhcnkoZHBseXIpDQojVGhpcyBMaWJyYXJ5IGlzIHVzZWQgZm9yIHJlYWRpbmcgRXhjZWwgZmlsZS4NCmxpYnJhcnkocmVhZHhsKQ0KI0ZvciBjYWxjdWxhdGluZyB0aGUgR2VvIGRpc3RhbmNlLg0KbGlicmFyeShnZW9zcGhlcmUpDQpgYGANCg0KUmVhZGluZyB0aGUgY3N2IGZpbGVzIG9mIGFsbCB0aGUgYWlybGluZXMgd2hvICdzIG9yaWdpbiBhaXJwb3J0IGlzIE5ld1lvcmsuDQpgYGB7cn0NCiNkYXRhPC1mcmVhZCgiRGV0YWlsZWRfU3RhdGlzdGljc19EZXBhcnR1cmVzLmNzdiIsc2tpcCA9IDcsc3RyaW5nc0FzRmFjdG9ycyA9IFRSVUUpDQpUb3RhbF9kYXRhPC0gDQogICBsaXN0LmZpbGVzKHBhdHRlcm4gPSAiKi5jc3YiKSAlPiUgDQogICAgbWFwX2RmKH5mcmVhZCguLHNraXAgPSA3LHN0cmluZ3NBc0ZhY3RvcnMgPSBUUlVFKSkNCmBgYA0KDQojRGF0YSBDbGVhbmluZw0KDQpOb3cgY2hlY2tpbmcgZm9yIHRoZSBOQSB2YWx1ZXMgZm9yIGJvdGggdHJhaW4gYW5kIHRlc3QgZGF0YSBzZXRzLg0KYGBge3J9DQojQ2hlY2tpbmcgdGhlIE5BICdTIGF0IGVudGlyZSBkYXRhIHNldCBvZiB0cmFpbiBhbmQgdGVzdA0KY2F0KCJUaGUgTnVtYmVyIG9mIE5BICdTIGluIHRoZSBkYXRhOiAiLCBzdW0oVG90YWxfZGF0YT09Im5hIikpDQojY2hlY2tpbmcgZm9yIHRoZSBlbXB0eSBzZWxscyBpbiB0aGUgdGFibGUNCmNhdCgiXG5UaGUgTnVtYmVyIG9mIGJsYW5rIGNlbGwgJ1MgaW4gdGhlIGRhdGE6ICIsIHN1bShUb3RhbF9kYXRhPT0iIikpDQpgYGANCkFzIHdlIHNlZSBhYm92ZSBvdXRwdXQgdGhlaXIgYXJlIDIwMCBlbXB0eSBzcGFjZXMgaW4gdGhlIHRyYWluaW5nIGRhdGEsIHNvIG5vdyB3ZSBhcmUgZ29pbmcgdG8gc2VlIHRoZSBlbXB0eSByb3dzIGZvciBmaW5kaW5nIHRoZSByZWFzb24gdGhhdCB3aHkgdGhleSBhcmUgZW1wdHkNCg0KTm93IHNlaW5nIGluIHdoaWNoIGNvbHVtbnMgZW1wdHkgc3BhY2VzIGFyZSBwcmVzZW50Lg0KYGBge3J9DQphcHBseShUb3RhbF9kYXRhLDIsZnVuY3Rpb24oeClzdW0oeD09IiIpKQ0KYGBgDQpBcyB3ZSBzZWUgYWJvdmUgdGhhdCAgVGFpbCBOdW1iZXIgaGFzIDIwMCBlbXB0eSBjZWxscy4NCg0KTm93IEkgYW0gZ29pbmcgdG8gc2VlIHRoZSByb3dzIG9mIHRoYXQgcGFydGljdWxhciBjb2x1bW4gdG8gZmluZCB0aGUgcmVhc29uIG9mIGVtcHR5IGNlbGxzDQpgYGB7cn0NCiNUaGlzIGNvbW1hbmQgaXMgdXNlIHRvIHNlZSBhbGwgdGhlIGVtcHR5IHJvd3MuDQpUb3RhbF9kYXRhW2BUYWlsIE51bWJlcmA9PSIiXQ0KYGBgDQpBcyB3ZSBzZWUgaW4gYWxsIHRoZXNlIHJvd3Mgc2NoZWR1bGVkIGRlcGFydHVyZSB0aW1lIHdhcyBnaXZlbiBidXQgQWN0dWFsIGRlcGFydHVyZSB0aW1lIDAwOjAwICxBY3R1YWwgZWxhcHNlZCB0aW1lIGlzIGFsc28gMCBhbmQgYWxsIHNvcnQgb2YgZGVsYXkgY29sdW1ucyBhcmUgYWxzbyAwICxzbyBieSB0aGlzIHdlIGNhbiBjb25jbHVkZSB0aGF0IHRoZSBmbGlnaHRzIGhhcyBnb3QgY2FuY2xlZCBmb3Igc29tZSByZWFzb24gb3IgdGhlIGRhdGEgaGFzIG5vdCBiZWVuIGNhcHR1cmVkIGZvciB0aGlzIHBhcnRpY3VsYXIgZmxpZ2h0cy5TbyB0aGlzIGtpbmQgb2YgZGF0YSBpcyBub3QgbXVjaCB1c2VkIGluIHRoZSBwcmVkaWN0aW9uIHNvIGZvciBub3cgd2UgYXJlIHJlbW92aW5nIGFsbCB0aGUgcm93cyB3aGljaCBhcmUgZW1wdHkuDQoNClJlbW92aW5nIGFsbCB0aGUgcm93cyB3aGljaCBhcmUgZW1wdHkuDQpgYGB7cn0NCnNldGtleShUb3RhbF9kYXRhLGBUYWlsIE51bWJlcmApDQpUb3RhbF9kYXRhPC1Ub3RhbF9kYXRhWyEiIl0NCmBgYA0KDQoNCk5vdyBhZ2FpbiBjaGVja2luZyB3aGVhdGhlciBhbGwgdGhlIGVtcHR5IGNlbGwgaGFzIGdvdCByZW1vdmVkIG9yIG5vdCBpbiB0cmFpbiBkYXRhDQpgYGB7cn0NCiNDaGVja2luZyB0aGUgTkEgJ1MgYXQgZW50aXJlIGRhdGEgc2V0IG9mIHRyYWluIGFuZCB0ZXN0DQpjYXQoIlRoZSBOdW1iZXIgb2YgYmxhbmsgY2VsbHMgIGF0IFRyYWluaW5nIGRhdGEgc2V0OiAiLCBzdW0oVG90YWxfZGF0YT09IiIpKQ0KYGBgDQoNCnNvIE5vdyB3ZSBvdXIgdHJhaW5pbmcgZGF0YSBzZXQgZnJlZSBvZiBlbXB0eSBjZWxscy4NCg0KR2VuZXJhbGx5IHdlIHNob3VsZCBmaW5kIGFuZCB0cmVhdGUgdGhlIG91dGxpZXJzIGJ1dCBkdWUgdG8gbGVzcyB0aW1lIGlzc3VlcyBhbmQgc29tZSBNYWNoaW5lIExlYXJuaW5nIEFsZ29yaXRobSB3aGljaCBpIGFtIHVzaW5nIHRvIGJ1aWxkIG1vZGVsIGFyZSByb2J1c3QgdG8gb3V0bGllciBzbyBmb3Igbm93IGkgYW0gbm90IGNvbnNpZGVyaW5nIGl0Lg0KDQojRmVhdHVyZSBFbmdpbmVlcmluZw0KDQpSZWFkaW5nIHRoZSBDb29yZGluYXRlcyBvZiB0aGUgRGVzdGluYXRpb24gQWlycG9ydHMgZnJvbSB0aGUgZmlsZS4NCmBgYHtyfQ0KbGF0X2xvbmc8LWFzLmRhdGEudGFibGUocmVhZF9leGNlbCgiTGF0X0xvbmcueGxzeCIpKQ0KI2NvbnZlcnRpbmcgc3RyaW5nIGNvbHVtbiBhcyBmYWN0b3IuDQpsYXRfbG9uZyREZXN0aW5hdGlvbjwtYXMuZmFjdG9yKGxhdF9sb25nJERlc3RpbmF0aW9uKQ0KYGBgDQoNCkFkZGluZyBsb25naXR1ZGUgYW5kIGxhdGl0dWRlIGNvbHVtbnMgZm9yIE9yaWdpbiBBaXJwb3J0LiANCmBgYHtyfQ0KI0FkZGluZyB0aGUgY29sdW1ucw0KVG90YWxfZGF0YSRgU3RhcnQgU3RhdGlvbiBMb25naXR1ZGVgPC0gLTczLjg2MzANClRvdGFsX2RhdGEkYFN0YXJ0IFN0YXRpb24gTGF0aXR1ZGVgPC0gNDAuNzYzNg0KYGBgDQoNCkFkZGluZyBMb25naXR1ZGUgYW5kIExhdGl0dWRlIG9mIERlc3RpbmF0aW9uIEFpcnBvcnRzLg0KYGBge3J9DQpUb3RhbF9kYXRhPC0gbWVyZ2UoVG90YWxfZGF0YSxsYXRfbG9uZyxieS54ID0iRGVzdGluYXRpb24gQWlycG9ydCIsYnkueSA9ICJEZXN0aW5hdGlvbiIpDQpgYGANCg0KQWRkaW5nIHRoZSBjb2x1bW4gb2YgR2VvX2Rpc3RhbmNlIGJldHdlZW4gc291cmNlIGFpcnBvcnQgdG8gZGVzdGluYXRpb24gYWlycG9ydC4NCmBgYHtyfQ0KVG90YWxfZGF0YVssZGlzdGFuY2UgOj0gcm91bmQoZGlzdEhhdmVyc2luZShtYXRyaXgoYyhgU3RhcnQgU3RhdGlvbiBMb25naXR1ZGVgLGBTdGFydCBTdGF0aW9uIExhdGl0dWRlYCksIG5jb2wgPSAyKSxtYXRyaXgoYyhMb25nLExhdCksbmNvbCA9IDIpLHI9NjM3ODEzNyksMildDQpgYGANCg0Kd2UgYXJlIHJlbW92aW5nIHRoZXNlIGNvbHVtbnMgYmVjYXVzZSB0aGVzZSBjb2x1bW5zIGRvZXMgbm90IGVmZmVjdCBvdXIgcHJlZGljdGlvbi4NCjEpIEZsaWdodCBOdW1iZXINCjIpIERlc3RpbmF0aW9uIEFpcnBvcnQNCjMpIENhcnJpZXIgQ29kZQ0KNCkgVGFpbCBOdW1iZXINCjUpIFN0YXJ0IFN0YXRpb24gTG9uZ2l0dWRlDQo2KSBTdGFydCBTdGF0aW9uIExhdGl0dWRlDQo3KSBMYXQNCjgpIExvbmcNCmBgYHtyfQ0KVG90YWxfZGF0YVsgLGA6PWAoYEZsaWdodCBOdW1iZXJgID0gTlVMTCwgYERlc3RpbmF0aW9uIEFpcnBvcnRgID0gTlVMTCxgQ2FycmllciBDb2RlYD0gTlVMTCxgVGFpbCBOdW1iZXJgPSBOVUxMLGBTdGFydCBTdGF0aW9uIExvbmdpdHVkZWA9TlVMTCxgU3RhcnQgU3RhdGlvbiBMYXRpdHVkZWA9TlVMTCxMYXQ9TlVMTCxMb25nPU5VTEwpXQ0KYGBgDQoNCg0Kc28gbm93IHdlIGFyZSBjb252ZXJ0aW5nIHRoZSBkYXRlICBjb2x1bW5zIHRvIHRoZSBkYXRlIGZvcm1hdGUuDQpgYGB7cn0NCiNOb3cgY29udmVydGluZyB0aGUgZGF0ZSBjb2x1bW4uDQojd2UgZm91bmQgMiBkYXRlIGZvcm1hdCBpbiBkYXRhDQptZHkgPC0gbWR5KFRvdGFsX2RhdGEkYERhdGUgKE1NL0REL1lZWVkpYCkNCmRteSA8LSBkbXkoVG90YWxfZGF0YSRgRGF0ZSAoTU0vREQvWVlZWSlgKQ0KbWR5W2lzLm5hKG1keSldIDwtIGRteVtpcy5uYShtZHkpXSAjIHNvbWUgZGF0ZXMgYXJlIGFtYmlndW91cywgaGVyZSB3ZSBnaXZlDQpUb3RhbF9kYXRhJGBEYXRlIChNTS9ERC9ZWVlZKWA8LSBtZHkgIyBtZHkgcHJlY2VkZW5jZSBvdmVyIGRteQ0KYGBgDQoNCk5vdyB3ZSBhcmUgZGl2aWRpbmcgdGhlIGZvbGxvd2luZyBjb2x1bW5zIGJ5IGhvdXJzIGFuZCBtaW51dGVzDQoxKTEpU2NoZWR1bGVkIGRlcGFydHVyZSB0aW1lDQoyKUFjdHVhbCBkZXBhcnR1cmUgdGltZQ0KYGBge3J9DQojTm93IHdlIGFyZSBkaXZpZGluZyBTY2hlZHVsZWQgZGVwYXJ0dXJlIHRpbWUgY29sdW1uIHRvIHNjaGVkdWxlZF9kZXBhcnR1cmVfdGltZV9ob3VycyBhbmQgc2NoZWR1bGVkX2RlcGFydHVyZV90aW1lX21pbnV0ZXMNClRvdGFsX2RhdGEkYFNjaGVkdWxlZCBkZXBhcnR1cmUgdGltZSBob3Vyc2A8LWhvdXIoc3RycHRpbWUoVG90YWxfZGF0YSRgU2NoZWR1bGVkIGRlcGFydHVyZSB0aW1lYCwgZm9ybWF0ID0gJyVIOiVNJywgJ0dNVCcpKQ0KVG90YWxfZGF0YSRgU2NoZWR1bGVkIGRlcGFydHVyZSB0aW1lIG1pbnV0ZXNgPC1taW51dGUoc3RycHRpbWUoVG90YWxfZGF0YSRgU2NoZWR1bGVkIGRlcGFydHVyZSB0aW1lYCxmb3JtYXQgPSAnJUg6JU0nLCAnR01UJykpDQojTm93IHdlIGFyZSBkaXZpZGluZyBBY3R1YWwgZGVwYXJ0dXJlIHRpbWUgZGVwYXJ0dXJlIHRpbWUgY29sdW1uIHRvIEFjdHVhbF9kZXBhcnR1cmVfdGltZV9ob3VycyBhbmQgQWN0dWFsX2RlcGFydHVyZV90aW1lX21pbnV0ZXMNClRvdGFsX2RhdGEkYEFjdHVhbCBkZXBhcnR1cmUgdGltZSBob3Vyc2A8LWhvdXIoc3RycHRpbWUoVG90YWxfZGF0YSRgQWN0dWFsIGRlcGFydHVyZSB0aW1lYCwgZm9ybWF0ID0gJyVIOiVNJywgJ0dNVCcpKQ0KVG90YWxfZGF0YSRgQWN0dWFsIGRlcGFydHVyZSB0aW1lIG1pbnV0ZXNgPC1taW51dGUoc3RycHRpbWUoVG90YWxfZGF0YSRgQWN0dWFsIGRlcGFydHVyZSB0aW1lYCxmb3JtYXQgPSAnJUg6JU0nLCAnR01UJykpDQoNCg0KI05vdyByZW1vdmluZyB0aGUgb3JpZ2luYWwgU2NoZWR1bGVkIGRlcGFydHVyZSB0aW1lIGNvbHVtbg0KVG90YWxfZGF0YSRgU2NoZWR1bGVkIGRlcGFydHVyZSB0aW1lYDwtTlVMTA0KI05vdyByZW1vdmluZyB0aGUgYWN0dWFsIGRlcGFydHVyZSB0aW1lIGNvbHVtbg0KVG90YWxfZGF0YSRgQWN0dWFsIGRlcGFydHVyZSB0aW1lYDwtTlVMTA0KI05vdyByZW1vdmluZyB0aGUgd2hlZWxzIG9mIHRpbWUgYXMgaXRzIG5vdCB1c2VmdWwgYXQgbW9kZWwgYnVpbGRpbmcuDQpUb3RhbF9kYXRhJGBXaGVlbHMtb2ZmIHRpbWVgPC1OVUxMDQpgYGANCg0KDQpOb3cgZXh0cmFjdGluZyBtb250aHMgYW5kIHdlZWtkYXlzIGZyb20gdGhlIERhdGUgY29sdW1uIGluIHRyYWluIGRhdGEgc2V0LlJlbW92aW5nIERhdGUgY29sdW1uDQpgYGB7cn0NCiN0aGlzIGNvbW1hbmQgaXMgdXNlIHRvIGV4dHJhY3QgbW9udGhzDQpUb3RhbF9kYXRhJG1vbnRoczwtYXMuZmFjdG9yKG1vbnRoKFRvdGFsX2RhdGEkYERhdGUgKE1NL0REL1lZWVkpYCkpDQojdGhpcyBjb21tYW5kIGlzIHVzZWQgdG8gZXh0cmFjdCB3ZWVrZGF5cw0KVG90YWxfZGF0YSR3ZWVrRGF5czwtYXMuZmFjdG9yKHdlZWtkYXlzKFRvdGFsX2RhdGEkYERhdGUgKE1NL0REL1lZWVkpYCkpDQoNCiNSZW1vdmluZyBEYXRlIGNvbHVtbg0KI3RyYWluJGBEYXRlIChNTS9ERC9ZWVlZKWA8LU5VTEwNCmBgYA0KDQoNCk5vdyBleHRyYWN0aW5nIHNlYXNvbnMgZnJvbSBEYXRlIGluIHRoZSB0cmFpbmluZyBkYXRhIHNldC53ZSBhcmUgZXh0cmFjdGluZyBzZWFzb25zIGFjY29yZGluZyB0byBVU0EuDQoxKSBTdW1tZXIgLSBKdW5lLEp1bHksQXVndXN0ICg2LDcsOCkNCjIpIEF1dHVtbiAtIFNlcHQsT2N0LE5vdiAoOSwxMCwxMSkNCjMpIFdpbnRlciAtIERlY2VtYmVyLEphbixGZWIgKDEyLDEsMikNCjQpIFNwcmluZyAtIE1hcmNoLEFwcmlhbCxNYXkgKDMsNCw1KQ0KTm93IGNyZWF0aW5nIHRoZSBuZXcgY29sdW1uIG9mIHNlYXNvbnMuDQpgYGB7cn0NCmluZHggPC0gc2V0TmFtZXMoIHJlcChjKCd3aW50ZXInLCAnc3ByaW5nJywgJ3N1bW1lcicsDQogICAgICAgICAgICAgICAgICAgJ2ZhbGwnKSxlYWNoPTMpLCBjKGMoMTIsMSwyKSxjKDMsNCw1KSxjKDYsNyw4KSxjKDksMTAsMTEpKSkNClRvdGFsX2RhdGFbLHNlYXNvbnMgOj0gYXMuZmFjdG9yKHVubmFtZShpbmR4W2FzLmNoYXJhY3Rlcihtb250aChUb3RhbF9kYXRhJGBEYXRlIChNTS9ERC9ZWVlZKWApKV0pKV0NCmBgYA0KDQpOb3cgZXh0cmFjdGluZyB5ZWFycyBmcm9tIHRoZSBkYXRlLg0KYGBge3J9DQpUb3RhbF9kYXRhJHllYXJzPC1hcy5mYWN0b3IoeWVhcihUb3RhbF9kYXRhJGBEYXRlIChNTS9ERC9ZWVlZKWApKQ0KYGBgDQoNCiMyMDE2DQoNCk5vdyB3ZSBhcmUgc3Vic2V0dGluZyBkYXRhIG9mIDIwMTYuDQpgYGB7cn0NCnRyYWluXzIwMTY8LVRvdGFsX2RhdGFbeWVhcnM9PSIyMDE2Il0NCiNleHRyYWN0aW5nIGRheSANCnRyYWluXzIwMTYkZGF5PC1hcy5mYWN0b3IoZGF5KHRyYWluXzIwMTYkYERhdGUgKE1NL0REL1lZWVkpYCkpDQpgYGANCg0KDQpIb2xpZGF5cyBsaXN0IG9mIFVTQSBhdCBZZWFyIDIwMTYuDQoNCkhvbGlkYXlzDQoNCkRheSAgICAgICAgICAgIERhdGVzDQoNCkZyaSAgICAgICAgIEphbiAxDQpNb24gICAgICAgICBKYW4gMTgNCk1vbiAgICAgICAgIEZlYiAxNQ0KRnJpICAgICAgICAgQXByIDE1DQpTdW4gICAgICAgICBNYXkgOA0KTW9uICAgICAgICAgTWF5IDMwDQpTdW4gICAgICAgICBKdW5lIDE5DQpNb24gICAgICAgICBKdWx5IDQNCk1vbiAgICAgICAgIFNlcHQgNQ0KTW9uICAgICAgICAgT2N0IDEwDQpGcmkgICAgICAgICBOb3YgMTENClRodXIgICAgICAgIE5vdiAyNA0KRnJpICAgICAgICAgTm92IDI1DQpNb24gICAgICAgICBEZWMgMjYNCg0KTm93IHdlIGFyZSBjcmVhdGluZyB0aGUgY29sdW1uIEhvbGlkYXkgZm9yIHRoZSB0cmFpbl8yMDE2IGRhdGEuDQpgYGB7cn0NCiNJbnNlcnRpbmcgdGhlIGhvbGlkYXkgY29sdW1uLiANCnRyYWluXzIwMTYkSG9saWRheTwtYXMuZmFjdG9yKGlmZWxzZSgodHJhaW5fMjAxNiRtb250aHMgPT0gIjEiICYgdHJhaW5fMjAxNiR3ZWVrRGF5cz09IkZyaWRheSIgJiB0cmFpbl8yMDE2JGRheT09IjEiKSB8ICh0cmFpbl8yMDE2JG1vbnRocyA9PSAiMSIgJiB0cmFpbl8yMDE2JHdlZWtEYXlzPT0iTW9uZGF5IiAmIHRyYWluXzIwMTYkZGF5PT0iMTgiKSB8ICh0cmFpbl8yMDE2JG1vbnRocyA9PSAiMiIgJiB0cmFpbl8yMDE2JHdlZWtEYXlzPT0iTW9uZGF5IiAmIHRyYWluXzIwMTYkZGF5PT0iMTUiKSB8ICh0cmFpbl8yMDE2JG1vbnRocyA9PSAiNCIgJiB0cmFpbl8yMDE2JHdlZWtEYXlzPT0iRnJpZGF5IiAmIHRyYWluXzIwMTYkZGF5PT0iMTUiKSB8KHRyYWluXzIwMTYkbW9udGhzID09ICI1IiAmIHRyYWluXzIwMTYkd2Vla0RheXM9PSJTdW5kYXkiICYgdHJhaW5fMjAxNiRkYXk9PSI4IikgfCh0cmFpbl8yMDE2JG1vbnRocyA9PSAiNSIgJiB0cmFpbl8yMDE2JHdlZWtEYXlzPT0iTW9uZGF5IiAmIHRyYWluXzIwMTYkZGF5PT0iMzAiKSB8KHRyYWluXzIwMTYkbW9udGhzID09ICI2IiAmIHRyYWluXzIwMTYkd2Vla0RheXM9PSJTdW5kYXkiICYgdHJhaW5fMjAxNiRkYXk9PSIxOSIpIHwodHJhaW5fMjAxNiRtb250aHMgPT0gIjciICYgdHJhaW5fMjAxNiR3ZWVrRGF5cz09Ik1vbmRheSIgJiB0cmFpbl8yMDE2JGRheT09IjQiKSB8KHRyYWluXzIwMTYkbW9udGhzID09ICI5IiAmIHRyYWluXzIwMTYkd2Vla0RheXM9PSJNb25kYXkiICYgdHJhaW5fMjAxNiRkYXk9PSI1IikgfCh0cmFpbl8yMDE2JG1vbnRocyA9PSAiMTAiICYgdHJhaW5fMjAxNiR3ZWVrRGF5cz09Ik1vbmRheSIgJiB0cmFpbl8yMDE2JGRheT09IjEwIikgfCh0cmFpbl8yMDE2JG1vbnRocyA9PSAiMTEiICYgdHJhaW5fMjAxNiR3ZWVrRGF5cz09IkZyaWRheSIgJiB0cmFpbl8yMDE2JGRheT09IjExIikgfCh0cmFpbl8yMDE2JG1vbnRocyA9PSAiMTEiICYgdHJhaW5fMjAxNiR3ZWVrRGF5cz09IlRodXJzZGF5IiAmIHRyYWluXzIwMTYkZGF5PT0iMjQiKSB8KHRyYWluXzIwMTYkbW9udGhzID09ICIxMSIgJiB0cmFpbl8yMDE2JHdlZWtEYXlzPT0iRnJpZGF5IiAmIHRyYWluXzIwMTYkZGF5PT0iMjUiKSB8KHRyYWluXzIwMTYkbW9udGhzID09ICIxMiIgJiB0cmFpbl8yMDE2JHdlZWtEYXlzPT0iTW9uZGF5IiAmIHRyYWluXzIwMTYkZGF5PT0iMjYiKT09IFRSVUUsMSwwKSkNCmBgYA0KDQoxIC0gbWVhbnMgeWVzIHRoZXJlIHdhcyAgaG9saWRheS4NCg0KMCAtIG1lYW5zIE5vIHRoZXJlIHdhcyBubyBob2xpZGF5Lg0KDQpIb2xpZGF5cyBsaXN0IG9mIFVTQSBhdCBZZWFyIDIwMTcuDQoNCiMyMDE3DQoNCk5vdyBzdWJzZXR0aW5nIHRoZSAyMDE3IGRhdGEgZnJvbSB0cmFpbi4NCmBgYHtyfQ0KdHJhaW5fMjAxNzwtVG90YWxfZGF0YVt5ZWFycz09IjIwMTciXQ0KI2V4dHJhY3RpbmcgZGF5IA0KdHJhaW5fMjAxNyRkYXk8LWFzLmZhY3RvcihkYXkodHJhaW5fMjAxNyRgRGF0ZSAoTU0vREQvWVlZWSlgKSkNCmBgYA0KDQoNCkhvbGlkYXlzIGxpc3Qgb2YgVVNBIGF0IFllYXIgMjAxNy4NCg0KSG9saWRheXMNCg0KRGF5ICAgICAgICAgICAgRGF0ZXMNCg0KTW9uZGF5ICAgICAgICAgSmFuIDINCk1vbmRheSAgICAgICAgIEphbiAxNg0KTW9uZGF5ICAgICAgICAgRmViIDIwDQpNb25kYXkgICAgICAgICBBcHJpbCAxNw0KU3VuZGF5ICAgICAgICAgTWF5IDE0DQpNb25kYXkgICAgICAgICBNYXkgMjkNClN1bmRheSAgICAgICAgIEp1bmUgMTgNClR1ZXNkYXkgICAgICAgIEp1bHkgNA0KTW9uZGF5ICAgICAgICAgU2VwdGVtYmVyIDA0DQpNb25kYXkgICAgICAgICBvY3RvYmVyIDA5DQpGcmlkYXkgICAgICAgICBOb3ZlbWJlciAxMA0KU2F0dXJkYXkgICAgICAgTm92ZW1iZXIgMTENCk1vbmRheSAgICAgICAgIE5vdmVtYmVyIDEzDQpUaHVyc2RheSAgICAgICBOb3ZlbWJlciAyMw0KRnJpZGF5ICAgICAgICAgTm92ZW1iZXIgMjQNCk1vbmRheSAgICAgICAgIERlY2VtYmVyIDI1DQoNCk5vdyB3ZSBhcmUgY3JlYXRpbmcgdGhlIGNvbHVtbiBIb2xpZGF5IGZvciB0aGUgdHJhaW5fMjAxNiBkYXRhLg0KYGBge3J9DQojSW5zZXJ0aW5nIHRoZSBob2xpZGF5IGNvbHVtbi4gDQp0cmFpbl8yMDE3JEhvbGlkYXkgPC0gYXMuZmFjdG9yKGlmZWxzZSgodHJhaW5fMjAxNyRtb250aHMgPT0gIjEiICYgdHJhaW5fMjAxNyR3ZWVrRGF5cz09Ik1vbmRheSIgJiB0cmFpbl8yMDE3JGRheT09IjIiKSB8ICh0cmFpbl8yMDE3JG1vbnRocyA9PSAiMSIgJiB0cmFpbl8yMDE3JHdlZWtEYXlzPT0iTW9uZGF5IiAmIHRyYWluXzIwMTckZGF5PT0iMTYiKSB8ICh0cmFpbl8yMDE3JG1vbnRocyA9PSAiMiIgJiB0cmFpbl8yMDE3JHdlZWtEYXlzPT0iTW9uZGF5IiAmIHRyYWluXzIwMTckZGF5PT0iMjAiKSB8ICh0cmFpbl8yMDE3JG1vbnRocyA9PSAiNCIgJiB0cmFpbl8yMDE3JHdlZWtEYXlzPT0iTW9uZGF5IiAmIHRyYWluXzIwMTckZGF5PT0iMTciKSB8KHRyYWluXzIwMTckbW9udGhzID09ICI1IiAmIHRyYWluXzIwMTckd2Vla0RheXM9PSJTdW5kYXkiICYgdHJhaW5fMjAxNyRkYXk9PSIxNCIpIHwodHJhaW5fMjAxNyRtb250aHMgPT0gIjUiICYgdHJhaW5fMjAxNyR3ZWVrRGF5cz09Ik1vbmRheSIgJiB0cmFpbl8yMDE3JGRheT09IjI5IikgfCh0cmFpbl8yMDE3JG1vbnRocyA9PSAiNiIgJiB0cmFpbl8yMDE3JHdlZWtEYXlzPT0iU3VuZGF5IiAmIHRyYWluXzIwMTckZGF5PT0iMTgiKSB8KHRyYWluXzIwMTckbW9udGhzID09ICI3IiAmIHRyYWluXzIwMTckd2Vla0RheXM9PSJUdWVzZGF5IiAmIHRyYWluXzIwMTckZGF5PT0iNCIpIHwodHJhaW5fMjAxNyRtb250aHMgPT0gIjkiICYgdHJhaW5fMjAxNyR3ZWVrRGF5cz09Ik1vbmRheSIgJiB0cmFpbl8yMDE3JGRheT09IjQiKSB8KHRyYWluXzIwMTckbW9udGhzID09ICIxMCIgJiB0cmFpbl8yMDE3JHdlZWtEYXlzPT0iTW9uZGF5IiAmIHRyYWluXzIwMTckZGF5PT0iOSIpIHwodHJhaW5fMjAxNyRtb250aHMgPT0gIjExIiAmIHRyYWluXzIwMTckd2Vla0RheXM9PSJGcmlkYXkiICYgdHJhaW5fMjAxNyRkYXk9PSIxMCIpIHwodHJhaW5fMjAxNyRtb250aHMgPT0gIjExIiAmIHRyYWluXzIwMTckd2Vla0RheXM9PSJTYXR1cmRheSIgJiB0cmFpbl8yMDE3JGRheT09IjExIikgfCh0cmFpbl8yMDE3JG1vbnRocyA9PSAiMTEiICYgdHJhaW5fMjAxNyR3ZWVrRGF5cz09Ik1vbmRheSIgJiB0cmFpbl8yMDE3JGRheT09IjEzIikgfCh0cmFpbl8yMDE3JG1vbnRocyA9PSAiMTEiICYgdHJhaW5fMjAxNyR3ZWVrRGF5cz09IlRodXJzZGF5IiAmIHRyYWluXzIwMTckZGF5PT0iMjMiKXwodHJhaW5fMjAxNyRtb250aHMgPT0gIjExIiAmIHRyYWluXzIwMTckd2Vla0RheXM9PSJGcmlkYXkiICYgdHJhaW5fMjAxNyRkYXk9PSIyNCIpfCh0cmFpbl8yMDE3JG1vbnRocyA9PSAiMTIiICYgdHJhaW5fMjAxNyR3ZWVrRGF5cz09Ik1vbmRheSIgJiB0cmFpbl8yMDE3JGRheT09IjI1IikgPT0gVFJVRSwxLDApKQ0KYGBgDQoNCk5vdyBqb2luaW5nIHRoZSBUd28geWVhcnMgZGF0YSBzZXQuDQpgYGB7cn0NClRvdGFsX2RhdGExPC1yYmluZChzZXREVCh0cmFpbl8yMDE2KSwgc2V0RFQodHJhaW5fMjAxNyksIGZpbGw9VFJVRSkNCiNyZW1vdmluZyB1bndhbnRlZCBkYXRhIHNldA0Kcm0odHJhaW5fMjAxNikNCnJtKHRyYWluXzIwMTcpDQpgYGANCg0KIzIwMTgNCmBgYHtyfQ0KdGVzdDwtVG90YWxfZGF0YVt5ZWFycz09IjIwMTgiXQ0KdGVzdCRkYXk8LWRheSh0ZXN0JGBEYXRlIChNTS9ERC9ZWVlZKWApDQpgYGANCg0KSG9saWRheXMgbGlzdCBvZiBVU0EgYXQgWWVhciAyMDE4Lg0KDQpIb2xpZGF5cw0KDQpEYXkgICAgICAgICAgICBEYXRlcw0KDQpNb25kYXkgICAgICAgIEphbiAxDQpNb25kYXkgICAgICAgIEphbiAxNQ0KTW9uZGF5ICAgICAgICBGZWIgMTkNClNhdHVyZGF5ICAgICAgTWFyY2ggMzENCk1vbmRheSAgICAgICAgTWF5IDI4DQpXZWRuZXNkYXkgICAgIEp1bHkgNA0KTW9uZGF5ICAgICAgICBTZXB0IDMNCk1vbmRheSAgICAgICAgTm92IDEyDQpUaHVyc2RheSAgICAgIE5vdiAyMg0KRnJpZGF5ICAgICAgICBOb3YgMjMgDQpUdWVzZGF5ICAgICAgIERlY2VtYmVyIDI1DQoNCk5vdyB3ZSBhcmUgY3JlYXRpbmcgdGhlIGNvbHVtbiBIb2xpZGF5IGZvciB0aGUgdHJhaW5fMjAxNiBkYXRhLg0KYGBge3J9DQojSW5zZXJ0aW5nIHRoZSBob2xpZGF5IGNvbHVtbi4gDQp0ZXN0JEhvbGlkYXk8LWFzLmZhY3RvcihpZmVsc2UoKHRlc3QkbW9udGhzID09ICIxIiAmIHRlc3Qkd2Vla0RheXM9PSJNb25kYXkiICYgdGVzdCRkYXk9PSIxIikgfCAodGVzdCRtb250aHMgPT0gIjEiICYgdGVzdCR3ZWVrRGF5cz09Ik1vbmRheSIgJiB0ZXN0JGRheT09IjE1IikgfCAodGVzdCRtb250aHMgPT0gIjIiICYgdGVzdCR3ZWVrRGF5cz09Ik1vbmRheSIgJiB0ZXN0JGRheT09IjE5IikgfCAodGVzdCRtb250aHMgPT0gIjMiICYgdGVzdCR3ZWVrRGF5cz09IlNhdHVyZGF5IiAmIHRlc3QkZGF5PT0iMzEiKSB8KHRlc3QkbW9udGhzID09ICI1IiAmIHRlc3Qkd2Vla0RheXM9PSJNb25kYXkiICYgdGVzdCRkYXk9PSIyOCIpIHwodGVzdCRtb250aHMgPT0gIjciICYgdGVzdCR3ZWVrRGF5cz09IldlZG5lc2RheSIgJiB0ZXN0JGRheT09IjQiKSB8KHRlc3QkbW9udGhzID09ICI5IiAmIHRlc3Qkd2Vla0RheXM9PSJNb25kYXkiICYgdGVzdCRkYXk9PSIzIikgfCh0ZXN0JG1vbnRocyA9PSAiMTEiICYgdGVzdCR3ZWVrRGF5cz09Ik1vbmRheSIgJiB0ZXN0JGRheT09IjEyIikgfCh0ZXN0JG1vbnRocyA9PSAiMTEiICYgdGVzdCR3ZWVrRGF5cz09IlRodXJzZGF5IiAmIHRlc3QkZGF5PT0iMjIiKSB8KHRlc3QkbW9udGhzID09ICIxMSIgJiB0ZXN0JHdlZWtEYXlzPT0iRnJpZGF5IiAmIHRlc3QkZGF5PT0iMjMiKSB8KHRlc3QkbW9udGhzID09ICIxMiIgJiB0ZXN0JHdlZWtEYXlzPT0iVHVlc2RheSIgJiB0ZXN0JGRheT09IjI1Iik9PSBUUlVFLDEsMCkpDQpgYGANCg0KSm9pbmluZyB0aGUgdGFibGVzLg0KYGBge3J9DQpUb3RhbF9kYXRhMTwtcmJpbmQoc2V0RFQoVG90YWxfZGF0YTEpLCBzZXREVCh0ZXN0KSwgZmlsbD1UUlVFKQ0KYGBgDQoNCiMyMDE5DQoNCmBgYHtyfQ0KdGVzdDwtVG90YWxfZGF0YVt5ZWFycz09IjIwMTkiXQ0KdGVzdCRkYXk8LWRheSh0ZXN0JGBEYXRlIChNTS9ERC9ZWVlZKWApDQpgYGANCg0KSG9saWRheXMgbGlzdCBvZiBVU0EgYXQgWWVhciAyMDE5Lg0KDQpIb2xpZGF5cw0KDQoNCg0KDQpSZWFzb24gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGF5ICAgICAgICAgICAgICAgICAgICAgICAgICAgRGF0ZSANCg0KDQoNCk5ldyBZZWFy4oCZcyBEYXkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1vbmRheSAgICAgICAgICAgICAgICAgICAgICAgIEphbnVhcnkgMQ0KDQpCaXJ0aGRheSBvZiBNYXJ0aW4gTHV0aGVyIEtpbmcgSnIuOiAgICAgICAgICAgICAgICAgICAgICAgTW9uZGF5ICAgICAgICAgICAgICAgICAgICAgICAgSmFudWFyeSAyMQ0KDQpCaXJ0aGRheSBvZiBHZW9yZ2UgV2FzaGluZ3RvbiAoUHJlc2lkZW504oCZcyBEYXkpOiAgICAgICAgICBNb25kYXkgICAgICAgICAgICAgICAgICAgICAgICBGZWJydWFyeSAxOA0KDQpNZW1vcmlhbCBEYXk6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTW9uZGF5ICAgICAgICAgICAgICAgICAgICAgICAgTWF5IDI3DQoNCkluZGVwZW5kZW5jZSBEYXk6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUaHVyc2RheSAgICAgICAgICAgICAgICAgICAgICBKdWx5IDQNCg0KTGFib3IgRGF5OiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1vbmRheSAgICAgICAgICAgICAgICAgICAgICAgIFNlcHRlbWJlciAyDQoNCkNvbHVtYnVzIERheTogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNb25kYXkgICAgICAgICAgICAgICAgICAgICAgICBPY3RvYmVyIDE0DQoNClZldGVyYW5zIERheTogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNb25kYXkgICAgICAgICAgICAgICAgICAgICAgICBOb3ZlbWJlciAxMQ0KDQpUaGFua3NnaXZpbmcgRGF5OiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVGh1cnNkYXkgICAgICAgICAgICAgICAgICAgICAgTm92ZW1iZXIgMjgNCg0KQ2hyaXN0bWFzIERheTogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFdlZG5lc2RheSAgICAgICAgICAgICAgICAgICAgIERlY2VtYmVyIDI1DQoNCg0KDQpPdGhlciBpbXBvcnRhbnQgaG9saWRheXMgdG8gbm90ZSB0aGF0IHlvdSBkb27igJl0IGdldCBvZmYgZm9yOg0KDQoNCkdyb3VuZGhvZyBEYXk6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTYXR1cmRheSAgICAgICAgICAgICAgICAgICAgICBGZWJydWFyeSAyDQoNClZhbGVudGluZeKAmXMgRGF5OiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRodXJzZGF5ICAgICAgICAgICAgICAgICAgICAgIEZlYnJ1YXJ5IDE0DQoNClNhaW50IFBhdHJpY2vigJlzIERheTogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN1bmRheSAgICAgICAgICAgICAgICAgICAgICAgIE1hcmNoIDE3DQoNClRheCBEYXk6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNb25kYXkgICAgICAgICAgICAgICAgICAgICAgICBBcHJpbCAxNQ0KDQpHb29kIEZyaWRheTogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRnJpZGF5ICAgICAgICAgICAgICAgICAgICAgICAgQXByaWwgMTkNCg0KRWFzdGVyOiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFN1bmRheSAgICAgICAgICAgICAgICAgICAgICAgIEFwcmlsIDIxDQoNCkNpbmNvIGRlIE1heW86ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdW5kYXkgICAgICAgICAgICAgICAgICAgICAgICBNYXkgNQ0KDQpNb3RoZXLigJlzIERheTogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTdW5kYXkgICAgICAgICAgICAgICAgICAgICAgICBNYXkgMTINCg0KRmF0aGVy4oCZcyBEYXk6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3VuZGF5ICAgICAgICAgICAgICAgICAgICAgICAgSnVuZSAxNg0KDQpIYWxsb3dlZW46ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVGh1cnNkYXkgICAgICAgICAgICAgICAgICAgICAgT2N0b2JlciAzMQ0KDQpCbGFjayBGcmlkYXk6ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRnJpZGF5ICAgICAgICAgICAgICAgICAgICAgICAgTm92ZW1iZXIgMjkNCmBgYHtyfQ0KI0luc2VydGluZyB0aGUgaG9saWRheSBjb2x1bW4uIA0KdGVzdCRIb2xpZGF5PC1hcy5mYWN0b3IoaWZlbHNlKCh0ZXN0JG1vbnRocyA9PSAiMSIgJiB0ZXN0JHdlZWtEYXlzPT0iTW9uZGF5IiAmIHRlc3QkZGF5PT0iMSIpIHwgKHRlc3QkbW9udGhzID09ICIxIiAmIHRlc3Qkd2Vla0RheXM9PSJNb25kYXkiICYgdGVzdCRkYXk9PSIyMSIpIHwgKHRlc3QkbW9udGhzID09ICIyIiAmIHRlc3Qkd2Vla0RheXM9PSJNb25kYXkiICYgdGVzdCRkYXk9PSIxOCIpIHwgKHRlc3QkbW9udGhzID09ICI1IiAmIHRlc3Qkd2Vla0RheXM9PSJNb25kYXkiICYgdGVzdCRkYXk9PSIyNyIpIHwodGVzdCRtb250aHMgPT0gIjciICYgdGVzdCR3ZWVrRGF5cz09IlRodXJzZGF5IiAmIHRlc3QkZGF5PT0iNCIpIHwodGVzdCRtb250aHMgPT0gIjkiICYgdGVzdCR3ZWVrRGF5cz09Ik1vbmRheSIgJiB0ZXN0JGRheT09IjIiKSB8KHRlc3QkbW9udGhzID09ICIxMCIgJiB0ZXN0JHdlZWtEYXlzPT0iTW9uZGF5IiAmIHRlc3QkZGF5PT0iMTQiKSB8KHRlc3QkbW9udGhzID09ICIxMSIgJiB0ZXN0JHdlZWtEYXlzPT0iTW9uZGF5IiAmIHRlc3QkZGF5PT0iMTEiKSB8KHRlc3QkbW9udGhzID09ICIxMSIgJiB0ZXN0JHdlZWtEYXlzPT0iVGh1cnNkYXkiICYgdGVzdCRkYXk9PSIyOCIpIHwodGVzdCRtb250aHMgPT0gIjEyIiAmIHRlc3Qkd2Vla0RheXM9PSJXZWRuZXNkYXkiICYgdGVzdCRkYXk9PSIyNSIpIHwodGVzdCRtb250aHMgPT0gIjIiICYgdGVzdCR3ZWVrRGF5cz09IlNhdHVyZGF5IiAmIHRlc3QkZGF5PT0iMiIpfCh0ZXN0JG1vbnRocyA9PSAiMiIgJiB0ZXN0JHdlZWtEYXlzPT0iVGh1cnNkYXkiICYgdGVzdCRkYXk9PSIxNCIpfCh0ZXN0JG1vbnRocyA9PSAiMyIgJiB0ZXN0JHdlZWtEYXlzPT0iU3VuZGF5IiAmIHRlc3QkZGF5PT0iMTciKXwodGVzdCRtb250aHMgPT0gIjQiICYgdGVzdCR3ZWVrRGF5cz09Ik1vbmRheSIgJiB0ZXN0JGRheT09IjE1Iil8KHRlc3QkbW9udGhzID09ICI0IiAmIHRlc3Qkd2Vla0RheXM9PSJGcmlkYXkiICYgdGVzdCRkYXk9PSIxOSIpfCh0ZXN0JG1vbnRocyA9PSAiNCIgJiB0ZXN0JHdlZWtEYXlzPT0iU3VuZGF5IiAmIHRlc3QkZGF5PT0iMjEiKXwodGVzdCRtb250aHMgPT0gIjUiICYgdGVzdCR3ZWVrRGF5cz09IlN1bmRheSIgJiB0ZXN0JGRheT09IjUiKXwodGVzdCRtb250aHMgPT0gIjUiICYgdGVzdCR3ZWVrRGF5cz09IlN1bmRheSIgJiB0ZXN0JGRheT09IjEyIil8KHRlc3QkbW9udGhzID09ICI2IiAmIHRlc3Qkd2Vla0RheXM9PSJTdW5kYXkiICYgdGVzdCRkYXk9PSIxNiIpfCh0ZXN0JG1vbnRocyA9PSAiMTAiICYgdGVzdCR3ZWVrRGF5cz09IlRodXJzZGF5IiAmIHRlc3QkZGF5PT0iMzEiKXwodGVzdCRtb250aHMgPT0gIjExIiAmIHRlc3Qkd2Vla0RheXM9PSJGcmlkYXkiICYgdGVzdCRkYXk9PSIyOSIpPT0gVFJVRSwxLDApKQ0KDQpgYGANCg0KSm9pbmluZyB0aGUgdGFibGVzLg0KYGBge3J9DQpUb3RhbF9kYXRhPC1yYmluZChzZXREVChUb3RhbF9kYXRhMSksIHNldERUKHRlc3QpLCBmaWxsPVRSVUUpDQpybShUb3RhbF9kYXRhMSkNCmBgYA0KDQpOb3cgZXh0cmFjdGluZyBNb3JuaW5nLE5vb24sRXZlbmluZyBhbmQgTmlnaHQsdGhlIGZvbGxvd2luZyB0aGUgdGltaW5nIGNsYXNzaWZpY2F0aW9ucy4NCjUgSG91cnMgIC0gMTEgSG91cnMgOi0gTW9ybmluZw0KMTIgSG91cnMgLSAxNiBIb3VycyA6LSBOb29uDQoxNyBIb3VycyAtIDE5IEhvdXJzIDotIEV2ZW5pbmcNCjIwIEhvdXJzIC0gNCBIb3VycyA6LSBOaWdodC4NCg0KTm93IGluc2VydGluZyB0aCBEYXlDeWNsZSBjb2x1bW4gaW50byB0cmFpbiBkYXRhIHNldC4NCmBgYHtyfQ0KVG90YWxfZGF0YVssRGF5Q3ljbGU6PWFzLmZhY3RvciggaWZlbHNlKA0KICBgU2NoZWR1bGVkIGRlcGFydHVyZSB0aW1lIGhvdXJzYCA+PSA1ICYgYFNjaGVkdWxlZCBkZXBhcnR1cmUgdGltZSBob3Vyc2A8PTExICwgJ01vcm5pbmcnLA0KICAgIGlmZWxzZShgU2NoZWR1bGVkIGRlcGFydHVyZSB0aW1lIGhvdXJzYCA+PSAxMiAmIGBTY2hlZHVsZWQgZGVwYXJ0dXJlIHRpbWUgaG91cnNgPD0xNiwnTm9vbicgLA0KICAgICAgaWZlbHNlKGBTY2hlZHVsZWQgZGVwYXJ0dXJlIHRpbWUgaG91cnNgID49IDE3ICYgYFNjaGVkdWxlZCBkZXBhcnR1cmUgdGltZSBob3Vyc2A8PTE5LCAnRXZlbmluZycsIA0KICAgICAgICAgICJOaWdodCIgICApDQogICAgKQ0KICApDQopDQpdDQpgYGANCg0KDQoNCmNyZWF0aW5nIHRoZSB0YXJnZXQgdmFyaWFibGUgYnkgdGhlIGZvcm11bGEgKChhY3R1YWxfZWxhcHNlZCB0aW1lIC0gc2NoZWR1bGVkX2VsYXBzZWQgdGltZSkrZGVwYXJ0dXJlIHRpbWUpPD0wIG5vX2RlbGF5ID49MSBpcyBkZWxheQ0KYGBge3J9DQojY3JlYXRpbmcgdGhlIHRhcmdldCB2YXJpYWJsZSB3aGljaCBpcyBjYXRlZ29yaWNhbCB2YXJpYWJsZS4NClRvdGFsX2RhdGEkRGVsYXk8LWFzLmZhY3RvcihpZmVsc2UoKFRvdGFsX2RhdGEkYEFjdHVhbCBlbGFwc2VkIHRpbWUgKE1pbnV0ZXMpYC0gVG90YWxfZGF0YSRgU2NoZWR1bGVkIGVsYXBzZWQgdGltZSAoTWludXRlcylgKStUb3RhbF9kYXRhJGBEZXBhcnR1cmUgZGVsYXkgKE1pbnV0ZXMpYCA8PSAwLDAsMSkpDQpgYGANCjEpIDEgLSBEZWxheWVkDQoyKSAwIC0gTm90IERlbGF5ZWQNCg0KTm93IHJlbW92aW5nIHVud2FudGVkIGZlYXR1cmVzIGZyb20gdGhlIHRyYWluIGRhdGEgc2V0Lg0KYGBge3J9DQpUb3RhbF8yMDE4PC1Ub3RhbF9kYXRhDQpUb3RhbF8yMDE4JHllYXJzPC1OVUxMDQpUb3RhbF8yMDE4JGRheTwtTlVMTA0KVG90YWxfMjAxOCRgRGF0ZSAoTU0vREQvWVlZWSlgPC1OVUxMDQpybSh0ZXN0KQ0KYGBgDQoNClJlbW92aW5nIHRoZSBhY3R1YWwgZWxhcHMgdGltZSAsU2NoZWR1bGVkIGVsYXBzZWQgdGltZSAoTWludXRlcyksRGVwYXJ0dXJlIGRlbGF5IChNaW51dGVzKSBmcm9tIHRyYWluaWcgYW5kIHRlc3RpbmcgZGF0YSBhcyB0aGVzZSB0aHJlZSBjb2x1bW5zIGFyZSBoaWdobHkgY29ycmVsYXRlZCB0byB0YXJnZXQgdmFyaWJsZS4NCmBgYHtyfQ0KI1JlbW92aW5nIGZyb20gdHJhaW5nIGRhdGENClRvdGFsXzIwMTgkYEFjdHVhbCBlbGFwc2VkIHRpbWUgKE1pbnV0ZXMpYDwtTlVMTA0KVG90YWxfMjAxOCRgRGVwYXJ0dXJlIGRlbGF5IChNaW51dGVzKWA8LU5VTEwNClRvdGFsXzIwMTgkYFNjaGVkdWxlZCBlbGFwc2VkIHRpbWUgKE1pbnV0ZXMpYDwtTlVMTA0KYGBgDQoNCg0KYGBge3J9DQojUGFyYW1ldGVyIGZvciB0aGUgZnVuY3Rpb24uDQojcGFyYW1ldGVyIDEgOi0gTnVtYmVyIG9mIGNvcnJlY3QgcHJlZGljdGlvbnMgZm9yIGNsYXNzIDANCiNwYXJhbWV0ZXIgMiA6LSBOdW1iZXIgb2Ygd3JvbmcgcHJlZGljdGlvbnMgZm9yIGNsYXNzIDANCiNwYXJhbWV0ZXIgMyA6LSBOdW1iZXIgb2YgY29ycmVjdCBwcmVkaWN0aW9ucyBmb3IgY2xhc3MgMQ0KI3BhcmFtZXRlciA0IDotIE51bWJlciBvZiB3cm9uZyBwcmVkaWN0aW9ucyBmb3IgY2xhc3MgMQ0KZ3JhcGhDb25mdXNpb25NYXRyaXg8LWZ1bmN0aW9uKGNvcnJlY3RfY2xhc3NfYSx3cm9uZ19jbGFzc19hLGNvcnJlY3RfY2xhc3NfYix3cm9uZ19jbGFzc19iKXsNCiAgDQogICNDcmVhdGluZyB0aGUgZGF0YSBmb3IgdGhlIHBsb3QuDQogIHggPC0gZGF0YS5mcmFtZSgiQWJvdXRfcmVzdWx0cyIgPSBjKCJDb3JyZWN0X1ByZWRpY3Rpb24iLCJXcm9uZ19QcmVkaWN0aW9uIiksICJWYWx1ZXMiID0gYyhjb3JyZWN0X2NsYXNzX2Esd3JvbmdfY2xhc3NfYSkpDQogIHkgPC0gZGF0YS5mcmFtZSgiQWJvdXRfcmVzdWx0cyIgPSBjKCJDb3JyZWN0X1ByZWRpY3Rpb24iLCJXcm9uZ19QcmVkaWN0aW9uIiksICJWYWx1ZXMiID0gYyhjb3JyZWN0X2NsYXNzX2Isd3JvbmdfY2xhc3NfYikpDQogIA0KICAjcGxvdGluZyB0aGUgZ3JhcGguDQogIHAgPC0gcGxvdF9seSgpICU+JQ0KICAgYWRkX3BpZShkYXRhID0gY291bnQoeCxBYm91dF9yZXN1bHRzKSwgbGFiZWxzID0gfkFib3V0X3Jlc3VsdHMsIHZhbHVlcyA9eCRWYWx1ZXMgLA0KICAgICAgICAgbmFtZSA9ICJjbGFzcyAwIiwgZG9tYWluID0gbGlzdChyb3cgPSAwLCBjb2x1bW4gPSAwKSkgJT4lDQogYWRkX3BpZShkYXRhID0gY291bnQoeSxBYm91dF9yZXN1bHRzKSwgbGFiZWxzID0gfkFib3V0X3Jlc3VsdHMsIHZhbHVlcyA9IHkkVmFsdWVzLA0KICAgICAgICAgbmFtZSA9ICJjbGFzcyAxIiwgZG9tYWluID0gbGlzdChyb3cgPSAwLCBjb2x1bW4gPSAxKSkgJT4lDQogICBsYXlvdXQodGl0bGUgPSAiVmlzdWFsaXphdGlvbiBPZiBDb25mdXNpb24gTWF0cml4IixzaG93bGVnZW5kID0gVCwNCiAgICAgICAgZ3JpZD1saXN0KHJvd3M9MSwgY29sdW1ucz0yKSwNCiAgICAgICAgeGF4aXMgPSBsaXN0KHNob3dncmlkID0gRkFMU0UsIHplcm9saW5lID0gRkFMU0UsIHNob3d0aWNrbGFiZWxzID0gRkFMU0UpLA0KICAgICAgICB5YXhpcyA9IGxpc3Qoc2hvd2dyaWQgPSBGQUxTRSwgemVyb2xpbmUgPSBGQUxTRSwgc2hvd3RpY2tsYWJlbHMgPSBGQUxTRSkpDQogICNEaXNwbGF5aW5nIHRoZSBncmFwaHMNCiAgcA0KICAjcmVtb3ZpbmcgdW53YW50ZWQgZGF0YWZyYW1lcy4NCiAgI3JtKHgpDQogICNybSh5KQ0KfQ0KYGBgDQoNCg0KYGBge3J9DQpuYW1lcyhUb3RhbF8yMDE4KSA8LSBtYWtlLm5hbWVzKG5hbWVzKFRvdGFsXzIwMTgpKQ0KYGBgDQoNCkVuY29kaW5nIHRoZSBkYXRhIGZvciBYR0Jvb3N0IE1vZGVsLg0KYGBge3J9DQojRW5jb2RpbmcgdGhlICBkYXRhIHNldA0KVG90YWxfZGF0YV9lbmNvZGVkPC1vbmVfaG90KFRvdGFsXzIwMTgpDQpgYGANCg0KV2hpbGUgZG9pbmcgb25laG90IGVuY29kaW5nIHdlIGhhdmUgZ290IHR3byBjb2x1bW5zIGZvciB0aGUgdGFyZ2V0IHZhcmlhYmxlLnNvIHdlIHNob3VsZCByZW1vdmUgb25lIG9mIHRoZSBjb2x1bW4NCmBgYHtyfQ0KVG90YWxfZGF0YV9lbmNvZGVkJERlbGF5XzA8LU5VTEwNCmBgYA0KDQoNCmBgYHtyfQ0KZHRlc3RmaW5hbDwteGdiLkRNYXRyaXgoYXMubWF0cml4KFRvdGFsX2RhdGFfZW5jb2RlZFssLSJEZWxheV8xIl0pLCBsYWJlbCA9IGFzLm1hdHJpeChUb3RhbF9kYXRhX2VuY29kZWQkRGVsYXlfMSkpDQpgYGANCg0KDQpOb3cgaW1wb3J0aW5nIG91dCBtb2RlbC4NCmBgYHtyfQ0KbW9kZWw8LSB4Z2IubG9hZCgneGdiX2FsbF9kYXRhLm1vZGVsJykNCmBgYA0KDQpOb3cgd2UgYXJlIGdvaW5nIHRvIGZpdCB0aGUgbmV3IGRhdGEgdG8gb3VyIE1vZGVsLg0KYGBge3J9DQp4Z2JwcmVkIDwtIHByZWRpY3QgKG1vZGVsLGR0ZXN0ZmluYWwsdHlwZSA9ICJjbGFzcyIpDQpgYGANCg0KQXMgb3VyIG1vZGVsIHRocmVzaG9sZCBpcyAwLjUsIG5vdyB3ZSBhcmUgY2xhc3NpZmluZyB0aGUgcHJlZGljdGlvbnMuDQpgYGB7cn0NCnhnYnByZWQgPC0gaWZlbHNlICh4Z2JwcmVkID49IDAuNSwxLDApDQpgYGANCg0KTm93IHdlIGFyZSBnb2luZyB0byBjaGVjayBvbiBjb25mdXNpb24gbWF0cml4DQpgYGB7cn0NCmNvbmZ1c2lvbk1hdHJpeChhcy5mYWN0b3IoVG90YWxfZGF0YV9lbmNvZGVkJERlbGF5XzEpLGFzLmZhY3Rvcih4Z2JwcmVkKSxwb3NpdGl2ZSA9ICIxIikNCmBgYA0KDQpgYGB7cn0NCmdyYXBoQ29uZnVzaW9uTWF0cml4KDIwMDQ5MCAsMjE5NTIsIDkxNDk5LDI3OTAzKQ0KYGBgDQoNCg0KDQpMZXRzIHNlZSB3aGljaCBpcyB0aGUgYmVzdCB0aHJlc2hvbGQgdmFsdWUgZm9yIG91ciBtb2RlbC4NCg0KTm93IERyYXdpbmcgdGhlIFJPQyBjVVJWRSBmb3IgZmluZGluZyBvdXQgdGhlIGlkZWFsIHRocmVzaG9sZCB2YWx1ZSBhdCB3aGljaCB0cnVlIHBvc2l0aXZlIGFuZCBmYWxzZSBwb3NpdGl2ZSBnZXQgYmFsYW5jZWQuDQpgYGB7cn0NClJPQ3ByZWQ8LXByZWRpY3Rpb24oeGdicHJlZCxUb3RhbF9kYXRhX2VuY29kZWQkRGVsYXlfMSkNClJPQ3BlcmY8LXBlcmZvcm1hbmNlKFJPQ3ByZWQsInRwciIsImZwciIpDQpwbG90KFJPQ3BlcmYsY29sPSJibHVlIixwcmludC5jdXRvZmZzLmF0PXNlcSgwLjEsYnk9MC4xLHRleHQuYWRqPWMoLTAuMiwxLjcpLGNleD0wLjcpKQ0KYGBgDQoNCnllcyBpdHMgcHJlZGljdGluZyBnb29kIGZvciB0aGUgdGVzdCBkYXRhLg0KDQpCdWlsZGluZyB0aGUgbW9kZWwgb24gdGhpcyBkYXRhLg0KYGBge3J9DQojZGVmYXVsdCBwYXJhbWV0ZXJzDQojcGFyYW1zIDwtIGxpc3QoYm9vc3RlciA9ICJnYnRyZWUiLCBvYmplY3RpdmUgPSAiYmluYXJ5OmxvZ2lzdGljIiwgZXRhPTAuMiwgbWF4X2RlcHRoPTQsIG1pbl9jaGlsZF93ZWlnaHQ9Miwgc3Vic2FtcGxlPTEsIGNvbHNhbXBsZV9ieXRyZWU9MSkNCg0KI2ZpbmQgYmVzdCBucm91bmQNCiNjdjwteGdiLmN2KCBwYXJhbXMgPSBwYXJhbXMsIGRhdGEgPSBkdGVzdGZpbmFsLCBucm91bmRzID0gMTAwMCwgbmZvbGQgPSA1LGdhbW1hPTAsIHNob3dzZCA9IFQsIHN0cmF0aWZpZWQgPSBULCBwcmludC5ldmVyeS5uID0gMTAsIGVhcmx5LnN0b3Aucm91bmQgPSAyMCwgbWF4aW1pemUgPSBGKQ0KI2N2JGJlc3RfaXRlcmF0aW9uDQojcHJpbnQoY3YpDQojcHJpbnQoY3YsIHZlcmJvc2U9VFJVRSkNCmBgYA0KDQpgYGB7cn0NCiNmaXJzdCBkZWZhdWx0IC0gbW9kZWwgdHJhaW5pbmcNCiN4Z2IxIDwtIHhnYi50cmFpbiAocGFyYW1zID0gcGFyYW1zLCBkYXRhID0gZHRlc3RmaW5hbCwgbnJvdW5kcyA9IDk3Mywgd2F0Y2hsaXN0ID0gbGlzdCh0cmFpbj1kdGVzdGZpbmFsKSwgcHJpbnQuZXZlcnkubiA9IDEwLCBlYXJseS5zdG9wLnJvdW5kID0gMTAsIG1heGltaXplID0gRiAsIGV2YWxfbWV0cmljID0gImVycm9yIikNCmBgYA0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQo=